﻿
using System.Linq;
using Stimulus360.Models.Data;
using System.Collections.Generic;
using Stimulus360.Models.Data.CustomTypes;

namespace Stimulus360.Repositories.Interfaces
{
    /// <summary>
    ///     This interface is used for CRUD operations across Ideas, Projects and investment categories.
    /// </summary>
    public interface IDataRepository
    {
        #region Projects
        /// <summary>
        ///     Method to retrieve the list of new projects in the system
        /// </summary>
        /// <returns>
        ///     List of new projects in the system
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate",
            Justification = "Method use is appropriate considering complexity and logic http://msdn.microsoft.com/en-us/library/bzwdh01d(VS.71).aspx#cpconpropertyusageguidelinesanchor1")]
        IQueryable<Project> GetNewProjects();


        /// <summary>
        ///     Method to get all projects in a given category in descending order of date submitted.
        /// </summary>
        /// <param name="category">
        ///     Category title of the Category
        /// </param>
        /// <returns>
        ///     All projects in the given category in descending order of date submitted.
        /// </returns>
        IQueryable<Project> FindProjectsInCategory(string category);

        /// <summary>
        ///     Method to retrieve list of projects satisfying the search criteria
        /// </summary>
        /// <param name="searchText">
        ///     The search criteria
        /// </param>
        /// <returns>
        ///     The list of projects satisfying the search criteria
        /// </returns>
        IQueryable<Project> FindProjectsBySearchString(string searchText);

        /// <summary>
        ///     Method to get the top N Projects ordered by Average rating
        /// </summary>
        /// <param name="topN">
        ///     Number of projects to be returned
        /// </param>
        /// <returns>
        ///     Top "N" projects ordered by Average rating
        /// </returns>
        IQueryable<Project> GetTopNProjects(int topN);

        /// <summary>
        ///     Method to get all projects depending of where Volunteers are required or not
        /// </summary>
        /// <param name="required">
        ///     Bool indicating if projects are required or not.
        /// </param>
        /// <returns>
        ///     All projects depending of where Volunteers are required or not
        /// </returns>
        IQueryable<Project> FindProjectsByVolunteerStatus(bool required);

        /// <summary>
        ///     Method to get all projects of the given status ordered by date submitted
        /// </summary>
        /// <param name="status">
        ///     The Status to be considered
        /// </param>
        /// <returns>
        ///    All projects of the given status ordered by date submitted
        /// </returns>
        IQueryable<Project> FindProjectsByStatus(ProjectStatus status);

        /// <summary>
        ///     Method to return the project for the given project ID
        /// </summary>
        /// <param name="projectId">
        ///     The project ID for which project has to be returned.
        /// </param>
        /// <returns>
        ///     Project for the given project ID
        /// </returns>
        Project FindProjectById(int projectId);

        /// <summary>
        ///     Method to get all feedback for the given project ordered by date submitted
        /// </summary>
        /// <param name="projectId">
        ///     Project ID of the project for which feedback is to be retrieved
        /// </param>
        /// <returns>
        ///     All feedback for the given project ordered by date submitted
        /// </returns>
        IQueryable<ProjectRating> GetProjectFeedback(int projectId);

        /// <summary>
        ///     This method is used to get the User's feedback for a specific Project
        /// </summary>
        /// <param name="projectId">
        ///     ProjectId for which feedback is to be retrieved.
        /// </param>
        /// <param name="userName">
        ///     User whose feedback is to be retrieved
        /// </param>
        /// <returns>
        ///     User Feedback for the given project.
        /// </returns>
        ProjectRating GetProjectFeedback(int projectId, string userName);

        /// <summary>
        ///     Method to retrieve list of volunteers for the given project
        /// </summary>
        /// <param name="projectId">
        ///     Project ID for which list of volunteers is to be retrieved
        /// </param>
        /// <returns>
        ///     List of volunteers for the given project
        /// </returns>
        IQueryable<Volunteer> GetProjectVolunteers(int projectId);

        /// <summary>
        ///     Method to updated an edited project to the database
        /// </summary>
        void UpdateProject();

        /// <summary>
        ///     Method to get the users favorite projects
        /// </summary>
        /// <param name="userName">
        ///     User whose favorite project list is to be retrieved
        /// </param>
        /// <returns>
        ///     The list of users favorite projects.
        /// </returns>
        IQueryable<Project> GetFavoriteProjects(string userName);

        /// <summary>
        ///     Method to get a list of recommended projects based on the users interests
        /// </summary>
        /// <param name="userName">
        ///     User for whom recommendations have to be made
        /// </param>
        /// <returns>
        ///     List of recommended projects.
        /// </returns>
        IQueryable<Project> GetRecommendedProjects(string userName);

        /// <summary>
        ///     Method to get a list of  projects for which the user has volunteered
        /// </summary>
        /// <param name="userName">
        ///     User under consideration
        /// </param>
        /// <returns>
        ///     List of volunteered projects.
        /// </returns>
        IQueryable<Project> GetVolunteeredProjects(string userName);

        /// <summary>
        ///     This method is used to create a new project in the DB
        /// </summary>
        /// <param name="project">
        ///     The project to be created
        /// </param>
        void CreateProject(Project project);
        #endregion

        #region Ideas
        /// <summary>
        ///     Method to get all the ideas in the system in descending order of date submitted.
        /// </summary>
        /// <returns>
        ///     All Ideas in descending order of date submitted
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate",
            Justification = "Method use is appropriate considering complexity and logic http://msdn.microsoft.com/en-us/library/bzwdh01d(VS.71).aspx#cpconpropertyusageguidelinesanchor1")]
        IQueryable<Idea> GetAllIdeas();

        /// <summary>
        ///     Method to get the new ideas in the system in descending order of date submitted.
        /// </summary>
        /// <returns>
        ///     New ideas in the system in descending order of date submitted.
        /// </returns>
        /// <remarks>
        ///     Current logic returns ideas submitted over the past 30 days(1 month)
        /// </remarks>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate",
            Justification = "Method use is appropriate considering complexity and logic http://msdn.microsoft.com/en-us/library/bzwdh01d(VS.71).aspx#cpconpropertyusageguidelinesanchor1")]
        IQueryable<Idea> GetNewIdeas();

        /// <summary>
        ///     Method to get all ideas in a given category in descending order of date submitted.
        /// </summary>
        /// <param name="category">
        ///     Category title of the Category
        /// </param>
        /// <returns>
        ///     All ideas in the given category in descending order of date submitted.
        /// </returns>
        IQueryable<Idea> FindIdeasInCategory(string category);

        /// <summary>
        ///     Method to get the top N ideas ordered by Average rating
        /// </summary>
        /// <param name="topN">
        ///     Number of ideas to be returned
        /// </param>
        /// <returns>
        ///     Top "N" ideas ordered by Average rating
        /// </returns>
        IQueryable<Idea> GetTopNIdeas(int topN);

        /// <summary>
        ///     Method to get all ideas of the given status ordered by date submitted
        /// </summary>
        /// <param name="status">
        ///     The Status to be considered
        /// </param>
        /// <returns>
        ///    All ideas of the given status ordered by date submitted
        /// </returns>
        IQueryable<Idea> FindIdeasByStatus(IdeaStatus status);

        /// <summary>
        ///     Method to save a new Idea
        /// </summary>
        /// <param name="idea">
        ///     Idea to be created.
        /// </param>
        void CreateIdea(Idea idea);

        /// <summary>
        ///     Method to return the Idea for the given idea ID
        /// </summary>
        /// <param name="ideaId">
        ///     The Idea ID for which Idea has to be returned.
        /// </param>
        /// <returns>
        ///     Idea for the given idea ID
        /// </returns>
        Idea FindIdeaById(int ideaId);

        /// <summary>
        ///     Method to updated an edited idea to the database
        /// </summary>
        void UpdateIdea();

        /// <summary>
        ///     Method to get all feedback for the given idea ordered by date submitted
        /// </summary>
        /// <param name="ideaId">
        ///     Idea ID of the idea for which feedback is to be retrieved
        /// </param>
        /// <returns>
        ///     All feedback for the given idea ordered by date submitted
        /// </returns>
        IQueryable<IdeaRating> GetIdeaFeedback(int ideaId);

        /// <summary>
        ///     This method is used to get the User's feedback for a specific Idea
        /// </summary>
        /// <param name="ideaId">
        ///     IdeaID for which feedback is to be retrieved.
        /// </param>
        /// <param name="userName">
        ///     User whose feedback is to be retrieved
        /// </param>
        /// <returns>
        ///     User Feedback for the given idea.
        /// </returns>
        IdeaRating GetIdeaFeedback(int ideaId, string userName);

        /// <summary>
        ///     Method to get list of projects associated with the idea
        /// </summary>
        /// <param name="ideaId">
        ///     IdeaID for which list of projects is to be retrieved.
        /// </param>
        /// <returns>
        ///     List of associated projects
        /// </returns>
        ICollection<ProjectSummary> GetProjectsForIdea(int ideaId);


        /// <summary>
        ///     Method to retrieve list of ideas satisfying the search criteria
        /// </summary>
        /// <param name="searchText">
        ///     The search criteria
        /// </param>
        /// <returns>
        ///     The list of ideas satisfying the search criteria
        /// </returns>
        IQueryable<Idea> FindIdeasBySearchString(string searchText);

        /// <summary>
        ///     Method to get the list of ideas submitted by the given user
        /// </summary>
        /// <param name="userName">
        ///     User whose submitted idea list is to be retrieved
        /// </param>
        /// <returns>
        ///     List of ideas submitted by the given user.
        /// </returns>
        IQueryable<Idea> GetSubmittedIdeas(string userName);

        /// <summary>
        ///     Method to get the users favorite ideas
        /// </summary>
        /// <param name="userName">
        ///     User whose favorite idea list is to be retrieved
        /// </param>
        /// <returns>
        ///     The list of users favorite ideas.
        /// </returns>
        IQueryable<Idea> GetFavoriteIdeas(string userName);

        /// <summary>
        ///     Method to get a list of recommended ideas based on the users interests
        /// </summary>
        /// <param name="userName">
        ///     User for whom recommendations have to be made
        /// </param>
        /// <returns>
        ///     List of recommended ideas.
        /// </returns>
        IQueryable<Idea> GetRecommendedIdeas(string userName); 
        #endregion

        #region InvestmentCategories
        /// <summary>
        ///     Method to return a summary of all the Investment Categories
        /// </summary>
        /// <returns>
        ///     Summary of all the Investment Categories
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate",
            Justification = "Method use is appropriate considering complexity and logic http://msdn.microsoft.com/en-us/library/bzwdh01d(VS.71).aspx#cpconpropertyusageguidelinesanchor1")]
        ICollection<InvestmentCategorySummary> GetAllInvestmentCategorySummaries(); 
        #endregion
    }

}
